package com.xiaoshuidi.cloud.module.finance.controller.admin.finance;

import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.excel.core.util.ExcelUtils;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.finance.controller.admin.finance.vo.transfer.*;
import com.xiaoshuidi.cloud.module.finance.convert.finance.FinanceConvert;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceBankTransferDO;
import com.xiaoshuidi.cloud.module.finance.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.finance.enums.order.BankTransferStatusEnum;
import com.xiaoshuidi.cloud.module.finance.service.finance.FinanceBankTransferService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Tag(name = "管理后台 - 应付款单")
@RestController
@RequestMapping("/finance/bank")
public class FinanceBankTransferController {

    @Resource
    private FinanceBankTransferService financeBankTransferService;

    @PostMapping("/transfer")
    @Operation(summary = "提交付款单")
    public CommonResult<Integer> transfer(@Valid @RequestBody FinanceBankTransferReqVO reqVO) {
        return CommonResult.success(financeBankTransferService.save(reqVO));
    }

    @GetMapping("/transfer/get")
    @Operation(summary = "付款单详情")
    @PreAuthorize("@ss.hasPermission('finance:transfer:query')")
    public CommonResult<FinanceBankTransferRespVO> detail(@RequestParam(value = "id", required = false) Integer id,
                                                          @RequestParam(value = "bizNo", required = false) String bizNo,
                                                          @RequestParam(value = "bizType", required = false) String bizType) {
        FinanceBankTransferDO financeBankTransferDO;
        if (id != null) {
            financeBankTransferDO = financeBankTransferService.getById(id);
        } else if (StringUtils.hasText(bizNo) && StringUtils.hasText(bizType)) {
            financeBankTransferDO = financeBankTransferService.getByBizNoAndBizType(bizNo, bizType);
        } else {
            throw new ServiceException(ErrorCodeConstants.FINANCE_BANK_TRANSFER_NOT_EXISTS);
        }
        return CommonResult.success(FinanceConvert.INSTANCE.map2(financeBankTransferDO));
    }

    @PostMapping("/transfer/{id}/update")
    @Operation(summary = "修改付款单")
    @PreAuthorize("@ss.hasPermission('finance:transfer:update')")
    public CommonResult<Void> edit(@PathVariable("id") Integer id, @RequestBody FinanceBankTransferReqVO reqVO) {
        reqVO.setOperator(SecurityFrameworkUtils.getLoginUser().getNickname());
        financeBankTransferService.update(id, reqVO);
        return CommonResult.success();
    }

    /**
     * 应付款单付款
     * @param id
     * @return
     */
    @PostMapping("/transfer/{id}/payment")
    @Operation(summary = "应付款单付款")
    @PreAuthorize("@ss.hasPermission('finance:transfer:payment')")
    public CommonResult<Void> payment(@PathVariable("id") Integer id) {
        FinanceBankTransferReqVO reqVO = new FinanceBankTransferReqVO();
        reqVO.setOperator(SecurityFrameworkUtils.getLoginUser().getNickname());
        financeBankTransferService.payment(id, reqVO);
        return CommonResult.success();
    }

    @GetMapping("/transfer/page")
    @Operation(summary = "应付款列表分页")
    @PreAuthorize("@ss.hasPermission('finance:transfer:query')")
    public CommonResult<FinanceBankTransferPageResult> page(FinanceBankTransferPageReqVO reqVO) {
        PageResult<FinanceBankTransferDO> pageResult = financeBankTransferService.getPage(reqVO);
        FinanceBankTransferPageResult result = financeBankTransferService.getFinanceBankTransferSummary(reqVO);
        PageResult<FinanceBankTransferRespVO> p = FinanceConvert.INSTANCE.convertToFinanceBankTransferPage(pageResult);
        result.setTotal(p.getTotal());
        result.setList(p.getList());
        return CommonResult.success(result);
    }

    /**
     * 批量付款
     *
     * @param ids
     * @return
     */
    @PostMapping("/transfer/payment-batch")
    @Operation(summary = "批量付款")
    @PreAuthorize("@ss.hasPermission('finance:transfer:payment_batch')")
    public CommonResult<Long> paymentBatch(@RequestBody List<Long> ids) {
        return CommonResult.success(financeBankTransferService.paymentBatch(ids));
    }

    /**
     * 批量打款单导出
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("/transfer/paymentNote/export")
    @PreAuthorize("@ss.hasPermission('finance:transfer:payment_batch_export')")
    public void paymentNoteExport(HttpServletResponse response, FinanceBankTransferPageReqVO reqVO) throws IOException {
        List<FinanceBankTransferDO> financeBankTransferDOS = financeBankTransferService.selectIds(reqVO.getIds());
        //导出记录
        financeBankTransferService.updateExportCount(reqVO.getIds());
        ExcelUtils.write(response, "批量应付款单.xlsx", "应付款单", FinanceBankTransferPayMentExcelVO.class
                , FinanceConvert.INSTANCE.convertToFinanceBankTransferPayMentExcelVO(financeBankTransferDOS));
    }

    /**
     * 导出
     *
     * @param response
     * @param reqVO
     * @throws IOException
     */
    @GetMapping("/transfer/export")
    @Operation(summary = "应付款列表导出")
    @PreAuthorize("@ss.hasPermission('finance:transfer:export')")
    public void export(HttpServletResponse response, FinanceBankTransferPageReqVO reqVO) throws IOException {
        reqVO.setPageSize(100);
        PageResult<FinanceBankTransferDO> pageResult = financeBankTransferService.getPage(reqVO);
        ExcelUtils.write(response, "应付款单.xlsx", "应付款单", FinanceBankTransferExcelVO.class, pageResult,
                FinanceConvert.INSTANCE::convertToFinanceBankTransferExcelVO, (pageNo) -> {
                    reqVO.setPageNo(pageNo);
                    return financeBankTransferService.getPage(reqVO);
                });
    }


    /**
     * 金蝶银企回调
     * @param reqVO
     * @return
     */
    @PostMapping("/transfer/callback")
    @Operation(summary = "金蝶银企转账回调")
    @PermitAll
    public Object transferCallback(@RequestParam Map<String, Object> reqVO) {
        log.info("金蝶银企转账回调: {}", JsonUtils.toJsonString(reqVO));

        Object number = reqVO.get("number");
        if (number == null || !StringUtils.hasText(number.toString())) {
            return JsonUtils.getObjectMapper().createObjectNode().put("message", "number不能为空")
                    .put("isSuccess", 1);
        }
        Object isSuccess = reqVO.get("isSuccess");
        Object tradeSerialNo = reqVO.get("trade_serial_no");
        FinanceBankTransferDO financeBankTransferDO = financeBankTransferService.getByNumber(number.toString());
        // 付款成功
        if (financeBankTransferDO != null && "0".equals(isSuccess)
                && !BankTransferStatusEnum.SUCCESS.name().equals(financeBankTransferDO.getStatus())) {
            financeBankTransferService.paySuccess(financeBankTransferDO, tradeSerialNo == null ? "" : tradeSerialNo.toString());
        } else if (financeBankTransferDO != null && !"0".equals(isSuccess)) {
            financeBankTransferService.payFailure(financeBankTransferDO);
        } else {
            log.info("金蝶银企转账未找到数据 {}", number);
        }
        return JsonUtils.getObjectMapper().createObjectNode().put("message", "成功")
                .put("isSuccess", 0);
    }
}
